{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "3637910d-2c6f-4f19-b1fb-2f916d23f9ac",
   "metadata": {},
   "source": [
    "# More advanced exercises\n",
    "\n",
    "Try creating a 3-way, perhaps bringing Gemini into the conversation! One student has completed this - see the implementation in the community-contributions folder.\n",
    "\n",
    "Try doing this yourself before you look at the solutions. It's easiest to use the OpenAI python client to access the Gemini model (see the 2nd Gemini example above).\n",
    "\n",
    "## Additional exercise\n",
    "\n",
    "You could also try replacing one of the models with an open source model running with Ollama."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "55044f9c-f444-4e35-b4c5-ef18abe26be4",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "from dotenv import load_dotenv\n",
    "from openai import OpenAI\n",
    "import anthropic\n",
    "from IPython.display import Markdown, display, update_display"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3d4dd1aa-664e-4c18-adaf-85610a39e494",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Load environment variables in a file called .env\n",
    "# Print the key prefixes to help with any debugging\n",
    "\n",
    "load_dotenv(override=True)\n",
    "openai_api_key = os.getenv('OPENAI_API_KEY')\n",
    "anthropic_api_key = os.getenv('ANTHROPIC_API_KEY')\n",
    "google_api_key = os.getenv('GOOGLE_API_KEY')\n",
    "\n",
    "if openai_api_key:\n",
    "    print(f\"OpenAI API Key exists and begins {openai_api_key[:8]}\")\n",
    "else:\n",
    "    print(\"OpenAI API Key not set\")\n",
    "    \n",
    "if anthropic_api_key:\n",
    "    print(f\"Anthropic API Key exists and begins {anthropic_api_key[:7]}\")\n",
    "else:\n",
    "    print(\"Anthropic API Key not set\")\n",
    "\n",
    "if google_api_key:\n",
    "    print(f\"Google API Key exists and begins {google_api_key[:8]}\")\n",
    "else:\n",
    "    print(\"Google API Key not set\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bcb54183-45d3-4d08-b5b6-55e380dfdf1b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Let's make a conversation between GPT-4o-mini and Claude-3-haiku\n",
    "# We're using cheap versions of models so the costs will be minimal\n",
    "\n",
    "gpt_model = \"gpt-4o-mini\"\n",
    "claude_model = \"claude-3-haiku-20240307\"\n",
    "gemini_model = \"gemini-2.0-flash\"\n",
    "\n",
    "gpt_system = \"You are third mate of the whaling ship Pequod. Your name is Flask. \\\n",
    "You approach the practice of whaling as if trying to avenge some deep offense the whales have done to you. \\\n",
    "You are chatting with Starbuck (the chief mate) and Ishmael (an oarsman)\"\n",
    "\n",
    "claude_system = \"You are the chief mate of the whaling ship Pequod. Your name is Starbuck. You are a thoughtful and intellectual \\\n",
    "Quaker from Nantucket who considers it madness to want revenge on an animal. \\\n",
    "You are chatting with two other users named Flask (the third mate) and Ishmael (an oarsman).\"\n",
    "\n",
    "gemini_system = \"You are an oarsman on the Pequod (a whaling ship). They call you Ishmael. You are interested in the history and mechanics \\\n",
    "of whaling and attempt to promote the nobility of the trade. \\\n",
    "You are chatting with two users named Flask (third mate) and Starbuck (the chief mate).\"\n",
    "\n",
    "gpt_messages = [\"Flask: Hi there\"]\n",
    "claude_messages = [\"Starbuck: Hi\"]\n",
    "gemini_messages = [\"Ishmael: Ahoy\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a3d08df6-a85b-4851-a7f9-83d024db729e",
   "metadata": {},
   "outputs": [],
   "source": [
    "openai = OpenAI()\n",
    "claude = anthropic.Anthropic()\n",
    "gemini = OpenAI(\n",
    "    api_key=google_api_key, \n",
    "    base_url=\"https://generativelanguage.googleapis.com/v1beta/openai/\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1df47dc7-b445-4852-b21b-59f0e6c2030f",
   "metadata": {},
   "outputs": [],
   "source": [
    "def call_gpt():\n",
    "    messages = [{\"role\": \"system\", \"content\": gpt_system}]\n",
    "    for gpt_message, claude_message, gemini_message in zip(gpt_messages, claude_messages, gemini_messages):\n",
    "        messages.append({\"role\": \"assistant\", \"content\": gpt_message})\n",
    "        messages.append({\"role\": \"user\", \"content\": claude_message})\n",
    "        messages.append({\"role\": \"user\", \"content\": gemini_message})\n",
    "        \n",
    "    completion = openai.chat.completions.create(\n",
    "        model=gpt_model,\n",
    "        messages=messages\n",
    "    )\n",
    "    return completion.choices[0].message.content"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7d2ed227-48c9-4cad-b146-2c4ecbac9690",
   "metadata": {},
   "outputs": [],
   "source": [
    "def call_claude():\n",
    "    messages = []\n",
    "    for gpt_message, claude_message, gemini_message in zip(gpt_messages, claude_messages, gemini_messages):\n",
    "        messages.append({\"role\": \"user\", \"content\": gpt_message})\n",
    "        messages.append({\"role\": \"assistant\", \"content\": claude_message})\n",
    "        messages.append({\"role\": \"user\", \"content\": gemini_message})\n",
    "        \n",
    "    messages.append({\"role\": \"user\", \"content\": gpt_messages[-1]})\n",
    "    \n",
    "    message = claude.messages.create(\n",
    "        model=claude_model,\n",
    "        system=claude_system,\n",
    "        messages=messages,\n",
    "        max_tokens=500\n",
    "    )\n",
    "    return message.content[0].text"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6e95b818-6daf-451e-9950-ecf5ab547bae",
   "metadata": {},
   "outputs": [],
   "source": [
    "def call_gemini():\n",
    "    messages = [{\"role\": \"system\", \"content\": gemini_system}]\n",
    "    for gpt_message, claude_message, gemini_message in zip(gpt_messages, claude_messages, gemini_messages):\n",
    "        messages.append({\"role\": \"user\", \"content\": gpt_message})\n",
    "        messages.append({\"role\": \"user\", \"content\": claude_message})\n",
    "        messages.append({\"role\": \"assistant\", \"content\": gemini_message})  \n",
    "    messages.append({\"role\": \"user\", \"content\": gpt_messages[-1]})\n",
    "    messages.append({\"role\": \"user\", \"content\": claude_messages[-1]})\n",
    "\n",
    "    response = gemini.chat.completions.create(\n",
    "        model=gemini_model,\n",
    "        messages=messages\n",
    "    )\n",
    "    return response.choices[0].message.content"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0275b97f-7f90-4696-bbf5-b6642bd53cbd",
   "metadata": {},
   "outputs": [],
   "source": [
    "gpt_messages = [\"Flask: Ahoy men\"]\n",
    "claude_messages = [\"Starbuck: Hello\"]\n",
    "gemini_messages = [\"Ishmael: Ahoy! Has seen the White Whale?\"]\n",
    "\n",
    "print(f\"{gpt_messages[0]}\\n\")\n",
    "print(f\"{claude_messages[0]}\\n\")\n",
    "print(f\"{gemini_messages[0]}\\n\")\n",
    "\n",
    "for i in range(5):\n",
    "    gpt_next = call_gpt()\n",
    "    print(f\"{gpt_next}\\n\")\n",
    "    gpt_messages.append(gpt_next)\n",
    "    \n",
    "    claude_next = call_claude()\n",
    "    print(f\"Starbuck: {claude_next}\\n\")\n",
    "    claude_messages.append(claude_next)\n",
    "\n",
    "    gemini_next = call_gemini()\n",
    "    print(f\"{gemini_next}\\n\")\n",
    "    gemini_messages.append(gemini_next)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c23224f6-7008-44ed-a57f-718975f4e291",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
